package com.maker.ai.service;

import com.maker.ai.entity.Rag;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.parser.apache.tika.ApacheTikaDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.filter.Filter;
import dev.langchain4j.store.embedding.filter.MetadataFilterBuilder;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class OptRagService {
    @Resource
    private RagService ragService;
    @Resource
    private EmbeddingModel embeddingModel;
    @Resource
    private EmbeddingStore<TextSegment> embeddingStore;


    /**
     * 新增 or 全量更新文档
     * @param filePath  文件路径
     * @return 本次向量 UUID
     */
    @Transactional(rollbackFor = Exception.class)
    public String ingestDocument(String filePath) throws FileNotFoundException {
        String fileName = Paths.get(filePath).getFileName().toString();
        FileInputStream fileInputStream = new FileInputStream(filePath);
        // 解析
        Document document = new ApacheTikaDocumentParser().parse(fileInputStream);
        // 分块、向量化、打新标签
        DocumentSplitter splitter = DocumentSplitters.recursive(1000, 50);
        List<TextSegment> segments = splitter.split(document);
        // 生成 UUID 作为整篇文档的 pointId
        String ragUuid = UUID.randomUUID().toString();
        // 5. 向量化 + 写入 Qdrant（把 UUID 放到 segment metadata）
        List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
        List<String> ids = segments.stream()
                .map(s -> UUID.randomUUID().toString())
                .toList();
        segments.forEach(s -> s.metadata().put("ragUuid", ragUuid));
        embeddingStore.addAll(ids, embeddings, segments);
        // 6. 落库
        Rag record = new Rag();
        record.setUuid(ragUuid);
        record.setName(fileName);
        //TODO 虚拟路径，结合实际存储位置路径
        record.setPath("虚拟路径，结合实际存储位置路径");
        record.setUploadTime(LocalDateTime.now());
        ragService.insert(record);

        log.info("文档 [{}] 已入库，uuid={}", fileName, ragUuid);
        return ragUuid;
    }
    /**
     *  更新文档
     * @param id  文档id
     * @param filePath 文件路径
     * @return 本次向量 UUID
     */
    @Transactional(rollbackFor = Exception.class)
    public String updateDocument(String id,String filePath) throws FileNotFoundException {
        String fileName = Paths.get(filePath).getFileName().toString();
        Rag rag = ragService.findById(id);
        FileInputStream fileInputStream = new FileInputStream(filePath);
        // 1. 解析
        Document document = new ApacheTikaDocumentParser().parse(fileInputStream);

        // 2. 分割
        DocumentSplitter splitter = DocumentSplitters.recursive(1000, 50);
        List<TextSegment> segments = splitter.split(document);

        // 3. 旧的UUID 作为整篇文档的 pointId
        String oldRagUuid = rag.getUuid();

        // 4. 如果库中已存在同名文件 -> 先删旧向量 + 旧记录
        if (rag != null) {
            // 构造过滤条件：metadata.ragUuid == 旧值
            Filter filter = MetadataFilterBuilder.metadataKey("ragUuid").isEqualTo(oldRagUuid);
            // 批量删除
            embeddingStore.removeAll(filter);   // 一句话搞定
//          ragService.deleteById(ragUuid);
        }
        // 3. 生成 UUID 作为整篇文档的 pointId
        String newRagUuid = UUID.randomUUID().toString();
        // 5. 向量化 + 写入 Qdrant（把 UUID 放到 segment metadata）
        List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
        List<String> newIds = segments.stream()
                .map(s -> UUID.randomUUID().toString())
                .toList();
        segments.forEach(s -> s.metadata().put("ragUuid", newRagUuid));
        embeddingStore.addAll(newIds, embeddings, segments);
        // 6. 落库
        Rag record = new Rag();
        record.setId(Long.parseLong( id));
        record.setUuid(newRagUuid);
        record.setName(fileName);
        //TODO 虚拟路径，结合实际存储位置路径
        record.setPath("虚拟路径，结合实际存储位置路径");
        record.setUploadTime(LocalDateTime.now());
        ragService.update(record);
        log.info("文档 [{}] 已更新入库，更新的uuid={}", fileName, newRagUuid);
        return newRagUuid;
    }





}
